package com.mystudio.android.calendar.view;


import java.util.List;

import android.app.Activity;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.text.format.Time;
import android.view.MotionEvent;
import android.view.View;

import com.mystudio.android.calendar.R;
import com.mystudio.android.calendar.constants.Constants;
import com.mystudio.android.calendar.model.Instance;
import com.mystudio.android.calendar.util.CPSyncUtil;
import com.mystudio.android.calendar.util.CalendarUtils;
import com.mystudio.android.calendar.util.ChineseCalendar;
import com.mystudio.android.util.Logger;

public class MyMonthView extends View {
	private static final Logger logger = new Logger(Constants.LOG_TAG, MyMonthView.class);
	private static final int CALENDAR_PAGE_WEEKS = 5;

	private static float mScale = 0; // Used for supporting different screen densities
    private static int WEEK_GAP = 0;
    private static int MONTH_DAY_GAP = 1;
    private static int MONTH_DAY_TEXT_SIZE = 14;
    private static int MONTH_DAY_TEXT_TOP_MARGIN = 0;
    private static int MONTH_DAY_TEXT_LEFT_MARGIN = 3;
    private static int MONTH_DAY_TEXT_BOTTOM_MARGIN = 0;
    private static int EVENT_TEXT_SIZE = 10;
    private static int EVENT_TEXT_TOP_MARGIN = 0;
    private static int EVENT_TEXT_LEFT_MARGIN = 2;
    private static int EVENT_TEXT_RIGHT_MARGIN = 2;
    private static int CHI_DAY_TEXT_SIZE = 10;
    private static int CHI_DAY_TEXT_TOP_MARGIN = 2;
    private static int CHI_DAY_TEXT_RIGHT_MARGIN = 2;
    
    private Activity mParentActivity;
    private Time mViewCalendar;
    private Time mToday;
    
    /**
     * The first day of week in default locale
     */
    private int mStartDay;
    
    /**
     * The first Julian day of the current month.
     */
    //private int mFirstJulianDay;

    /**
     * The top left Julian day of the top bitmap page.
     */
    private int mTopLeftJulianDayOfTop;
    private int mTopLeftJulianDayOfBottom = 0;
    private int mCurrentMonth;

    // For drawing to an off-screen Canvas
    private Bitmap mBitmap1;
    private Canvas mCanvas1;
    private Bitmap mBitmap2;
    private Canvas mCanvas2;
    private boolean mRedrawScreen = true;
    private Rect mBitmapRect = new Rect();
    private Rect mCanvasRect = new Rect();
    private float mLastY = -2000;
    
    // Pre-allocate and reuse
    private Rect mRect = new Rect();
    
    private int mCellHeight;
    private int mCellWidth;
    
    //List<Instance> mInstances;
    int[] eventTextY = new int[7* CALENDAR_PAGE_WEEKS];  // init in drawBox, for drawEvents use
    
    // Cached colors
    private static int mMonthBorderColor;
    private static int mMonthBgColor;
    private static int mMonthDayNumberColor;
    private static int mMonthChiDayNumberColor;
    private static int mMonthOtherMonthBgColor;
    private static int mMonthOtherMonthDayNumberColor;
    private static int mMonthTodayBgColor;
    private static int mMonthTodayNumberColor;
    private static int mMonthSundayBgColor;
    private static int mMonthSundayNumberColor;
    private static int mMonthSaturdayBgColor;
    private static int mMonthSaturdayNumberColor;
    
    public MyMonthView(Activity activity) {
    	super(activity);
    	
    	if (mScale == 0) {
    		mScale = getContext().getResources().getDisplayMetrics().density;
    		if (mScale != 1) {
    			WEEK_GAP *= mScale;
    			MONTH_DAY_GAP *= mScale;
    			MONTH_DAY_TEXT_SIZE *= mScale;
    		    MONTH_DAY_TEXT_TOP_MARGIN *= mScale;
    		    MONTH_DAY_TEXT_LEFT_MARGIN *= mScale;
    		    MONTH_DAY_TEXT_BOTTOM_MARGIN *= mScale;
    		    EVENT_TEXT_SIZE *= mScale;
    		    EVENT_TEXT_TOP_MARGIN *= mScale;
    		    EVENT_TEXT_LEFT_MARGIN *= mScale;
    		    EVENT_TEXT_RIGHT_MARGIN *= mScale;
    		    CHI_DAY_TEXT_SIZE *= mScale;
    		    CHI_DAY_TEXT_TOP_MARGIN *= mScale;
    		    CHI_DAY_TEXT_RIGHT_MARGIN *= mScale;
    		}
    	}

        init(activity);
    }
    
    private void init(Activity activity) {
        setFocusable(true);
        setClickable(true);
        //setOnCreateContextMenuListener(this);
        
        // Get Julian day no. of first day of this month
        // Get first day of week
        mParentActivity = activity;
        mViewCalendar = new Time();
        long now = System.currentTimeMillis();
        mViewCalendar.set(now);
        mViewCalendar.monthDay = 1;
        long millis = mViewCalendar.normalize(true /* ignore DST */);
        mCurrentMonth = mViewCalendar.month;
        int mFirstJulianDay = Time.getJulianDay(millis, mViewCalendar.gmtoff);
        mStartDay = CalendarUtils.getFirstDayOfWeek();

        // Get Julian day no. of top left day of this month
        int offset = mViewCalendar.weekDay - mStartDay;
        if (offset < 0) {
        	offset += 7;
        }
        mTopLeftJulianDayOfTop = mFirstJulianDay - offset;
        

        
        mViewCalendar.set(now);

        mToday = new Time();
        mToday.set(System.currentTimeMillis());

        //mResources = activity.getResources();

        // Cache color lookups
        Resources res = getResources();
        mMonthBorderColor = res.getColor(R.color.month_border);
        mMonthBgColor = res.getColor(R.color.month_bg);
        mMonthDayNumberColor = res.getColor(R.color.month_day_number);
        mMonthChiDayNumberColor = res.getColor(R.color.month_chi_day_number);
        mMonthOtherMonthBgColor = res.getColor(R.color.month_other_month_bg);
        mMonthOtherMonthDayNumberColor = res.getColor(R.color.month_other_month_day_number);
        mMonthTodayBgColor = res.getColor(R.color.month_today_bg);
        mMonthTodayNumberColor = res.getColor(R.color.month_today_day_number);
        mMonthSundayBgColor = res.getColor(R.color.month_sun_bg);
        mMonthSundayNumberColor = res.getColor(R.color.month_sun_day_number);
        mMonthSaturdayBgColor = res.getColor(R.color.month_sat_bg);
        mMonthSaturdayNumberColor = res.getColor(R.color.month_sat_day_number);
    }
    
    public void setSelectedTime(Activity activity, Time time) {
        // Save the selected time so that we can restore it later when we switch views.
        //mSavedTime.set(time);

    	// Get Julian day no. of first day of this month
        mViewCalendar.set(time);
        mViewCalendar.monthDay = 1;
        long millis = mViewCalendar.normalize(true /* ignore DST */);
        int mFirstJulianDay = Time.getJulianDay(millis, mViewCalendar.gmtoff);

        // Get Julian day no. of top left day of this month
        int offset = mViewCalendar.weekDay - mStartDay;
        if (offset < 0) {
        	offset += 7;
        }
        mTopLeftJulianDayOfTop = mFirstJulianDay - offset;
        
        mViewCalendar.set(time);

        mRedrawScreen = true;
        invalidate();
    }
    
    @Override
    protected void onSizeChanged(int width, int height, int oldw, int oldh) {
        drawingCalc(width, height);
        // If the size changed, then we should rebuild the bitmaps...
        //clearBitmapCache();
    }
    
    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        // No need to hang onto the bitmaps...
        //clearBitmapCache();
        if (mBitmap1 != null) {
            mBitmap1.recycle();
        }
        if (mBitmap2 != null) {
            mBitmap2.recycle();
        }
    }
    
    @Override
    protected void onDraw(Canvas canvas) {
    	if (mRedrawScreen) {
			if (mCanvas1 == null) {
				drawingCalc(getWidth(), getHeight());
			}

            // If we are zero-sized, the canvas will remain null so check again
            if (mCanvas1 != null) {
                // Clear the background
                final Canvas bitmapCanvas = mCanvas1;
                bitmapCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
                drawCalendar(mTopLeftJulianDayOfTop, mCurrentMonth, mToday, mCellWidth, mCellHeight, mParentActivity, bitmapCanvas, mRect, mViewCalendar, eventTextY);
                mRedrawScreen = false;
            }
        }

        // If we are zero-sized, the bitmap will be null so guard against this
        if (mBitmap1 != null) {
        	logger.info("mBitmapRect: " + mBitmapRect.top + "," + mBitmapRect.left + "," + mBitmapRect.right + "," + mBitmapRect.bottom);
        	
        	if (mBitmapRect.bottom > mCanvas1.getHeight()) {
        		if (mTopLeftJulianDayOfBottom != mTopLeftJulianDayOfTop + CALENDAR_PAGE_WEEKS*7) {
					mTopLeftJulianDayOfBottom = mTopLeftJulianDayOfTop + CALENDAR_PAGE_WEEKS*7;
					final Canvas bitmapCanvas = mCanvas2;
					bitmapCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
					drawCalendar(mTopLeftJulianDayOfBottom, mCurrentMonth, mToday, mCellWidth, mCellHeight, mParentActivity, bitmapCanvas, mRect, mViewCalendar, eventTextY);
        		}

				mRect.left = mBitmapRect.left;
				mRect.right = mBitmapRect.right;
				
				mCanvasRect.top = 0;
				mRect.top = mBitmapRect.top;
				mRect.bottom = mCanvas1.getHeight()-1;
				mCanvasRect.bottom = mRect.height()-1;
				canvas.drawBitmap(mBitmap1, mRect, mCanvasRect, null);

				mCanvasRect.top = mRect.height();
				mRect.top = 0;
				mRect.bottom = mBitmapRect.bottom - mCanvas1.getHeight();
				mCanvasRect.bottom = mCanvasRect.top + mRect.height() - 1;			
				canvas.drawBitmap(mBitmap2, mRect, mCanvasRect, null);
				
        	} else {
        		canvas.drawBitmap(mBitmap1, mBitmapRect, mBitmapRect, null);
        	}
        }
    }
    
    @Override
    public boolean onTouchEvent(MotionEvent event) { 
    	//dumpEvent(event);
    	
        int action = event.getAction();
        int actionCode = action & MotionEvent.ACTION_MASK;
    	switch (actionCode) {
    		case MotionEvent.ACTION_DOWN:
    			mLastY = event.getY(event.getPointerId(0));
    			break;
    			
    		case MotionEvent.ACTION_MOVE:
    			float thisY = event.getY(event.getPointerId(0));
    			logger.info(mLastY + "-" + thisY);
    			if (mLastY > -1000) {
    				mBitmapRect.offset(0, (int)(mLastY - thisY));
    			}
    			mLastY = thisY;
    			invalidate();
    			break;
    			
    		case MotionEvent.ACTION_UP:
    			if (mLastY > -1000) {
    				mBitmapRect.offset(0, (int)(event.getY(event.getPointerId(0)) - mLastY));
    			}
    			mLastY = -2000;
    			invalidate();
    			break;
    	}
    	
    	return true; // indicate event was handled
    }
    
    /** Show an event in the LogCat view, for debugging */
    private void dumpEvent(MotionEvent event) {
       String names[] = { "DOWN" , "UP" , "MOVE" , "CANCEL" , "OUTSIDE" ,
          "POINTER_DOWN" , "POINTER_UP" , "7?" , "8?" , "9?" };
       StringBuilder sb = new StringBuilder();
       int action = event.getAction();
       int actionCode = action & MotionEvent.ACTION_MASK;
       sb.append("event ACTION_" ).append(names[actionCode]);
       if (actionCode == MotionEvent.ACTION_POINTER_DOWN
             || actionCode == MotionEvent.ACTION_POINTER_UP) {
          sb.append("(pid " ).append(
          action >> MotionEvent.ACTION_POINTER_ID_SHIFT);
          sb.append(")" );
       }
       sb.append("[" );
       for (int i = 0; i < event.getPointerCount(); i++) {
          sb.append("#" ).append(i);
          sb.append("(pid " ).append(event.getPointerId(i));
          sb.append(")=" ).append((int) event.getX(i));
          sb.append("," ).append((int) event.getY(i));
          if (i + 1 < event.getPointerCount())
             sb.append(";" );
       }
       sb.append("]" );
       logger.info(sb.toString());
    }
    
    /**
     * Draw a page of calendar with fixed no. of weeks on given canvas of bitmap
     * 
     * @param topLeftJulianDay top left julian day of the page
     * @param currentMonth current month for highlight (0-11)
     * @param mToday today time object for highlight
     * @param mCellWidth cell width
     * @param mCellHeight cell height
     * @param canvas Canvas of bitmap for drawing
     * @param rect Rect object for reuse
     * @param viewCalendar time object for reuse
     * @param event text y position array for reuse
     * @param
     */
    private static void drawCalendar(int topLeftJulianDay, int currentMonth, Time mToday, int mCellWidth, int mCellHeight, Activity activity, Canvas canvas, Rect rect, Time viewCalendar, int[] eventTextY) {
    	//boolean isLandscape = view.getResources().getConfiguration().orientation
    	//	== Configuration.ORIENTATION_LANDSCAPE;

    	Paint p = new Paint();
    	Rect r = rect;
        
        // Get the day for the date at top left cell
    	Time tempDay = new Time();
    	tempDay.setJulianDay(topLeftJulianDay);
    	tempDay.normalize(true);

        for (int row = 0; row < CALENDAR_PAGE_WEEKS; row++) {
            for (int column = 0; column < 7; column++) {
                drawBox(tempDay, currentMonth, mToday, mCellWidth, mCellHeight, row, column, canvas, p, r, eventTextY);
                
                tempDay.monthDay += 1;
                tempDay.normalize(true);
            }
        }

        drawGrid(canvas, mCellWidth, mCellHeight, p);
        drawEvents(topLeftJulianDay, mCellWidth, mCellHeight, activity, canvas, p, r, eventTextY);
        
        eventTextY = null;  // free memory
    }
    
    /**
     * Draw a single box with calendar day text onto the canvas.
     * 
     * @param day The day (1-31).
     * @param day The current month (0-11).
     * @param mToday today time object for highlight
     * @param mCellWidth cell width
     * @param mCellHeight cell height
     * @param row The row of the box (0 - [CALENDAR_PAGE_WEEKS-1]).
     * @param column The column of the box (0-6).
     * @param canvas The canvas to draw on.
     * @param p The paint used for drawing.
     * @param r The rectangle used for each box.
     */
    private static void drawBox(Time day, int currentMonth, Time mToday, int mCellWidth, int mCellHeight, int row, int column, Canvas canvas, Paint p,
            Rect r, int[] eventTextY) {

        boolean isToday = false;
        if (day.monthDay == mToday.monthDay && day.year == mToday.year
                && day.month == mToday.month) {
            isToday = true;
        }

        int y = WEEK_GAP + row*(WEEK_GAP + mCellHeight);
        int x = column*(MONTH_DAY_GAP + mCellWidth);

        r.left = x;
        r.top = y;
        r.right = x + mCellWidth;
        r.bottom = y + mCellHeight;

        // Adjust the left column, right column, and bottom row to leave
        // no border.
        if (column == 0) {
            r.left = -1;
        } else if (column == 6) {
            r.right += 2;
        }

        if (row == CALENDAR_PAGE_WEEKS-1) {
            r.bottom = canvas.getHeight();
        }

        // Draw the cell contents (excluding monthDay number)
        int bgColor = mMonthBgColor, textColor = mMonthDayNumberColor;
        if (day.month != currentMonth) {
        	bgColor = mMonthOtherMonthBgColor;
        	textColor = mMonthOtherMonthDayNumberColor;
        } else if (isToday) {
           	//bgColor = mMonthTodayBgColor;
           	textColor = mMonthTodayNumberColor;
        } else if (day.weekDay == Time.SUNDAY){
        	bgColor = mMonthSundayBgColor;
           	textColor = mMonthSundayNumberColor;
        } else if (day.weekDay == Time.SATURDAY){
        	bgColor = mMonthSaturdayBgColor;
           	textColor = mMonthSaturdayNumberColor;
        }
        p.setStyle(Style.FILL);
        p.setColor(bgColor);
        canvas.drawRect(r, p);

        //drawEvents(day, canvas, r, p, !isToday /*draw bb background*/);

        // Draw the monthDay number
        p.setStyle(Paint.Style.FILL);
        p.setAntiAlias(true);
        p.setTypeface(null);
        p.setTextSize(MONTH_DAY_TEXT_SIZE);
        
        /*Drawing of day number is done here
         *easy to find tags draw number draw day*/
        p.setTextAlign(Paint.Align.LEFT);
        // center of text
        Paint.FontMetricsInt fm = p.getFontMetricsInt();
        int textX = r.left + MONTH_DAY_TEXT_LEFT_MARGIN;
        int textY = (int) (r.top + Math.abs(fm.top) + MONTH_DAY_TEXT_TOP_MARGIN); // bottom of text
        int textBottom = textY + Math.abs(fm.bottom) + MONTH_DAY_TEXT_BOTTOM_MARGIN;

        // Draw today background
        if (isToday) {
            p.setColor(mMonthTodayBgColor);
            r.bottom = textBottom;
            canvas.drawRect(r, p);
        }

        p.setColor(textColor);
        canvas.drawText(String.valueOf(day.monthDay), textX, textY, p);
        
        eventTextY[row*7+column] = textBottom;
        
        // Draw chinese calendar day
        p.setTextAlign(Paint.Align.RIGHT);
        p.setTextSize(CHI_DAY_TEXT_SIZE);
        p.setColor(mMonthChiDayNumberColor);
        fm = p.getFontMetricsInt();
        textX = r.right - CHI_DAY_TEXT_RIGHT_MARGIN;
        textY = (int) (r.top + Math.abs(fm.top) + CHI_DAY_TEXT_TOP_MARGIN); // bottom of text
        String chiDayText = new ChineseCalendar.SolarDate(
				day.year, day.month+1, day.monthDay).toLunarDate().getDayDesc();
        canvas.drawText(chiDayText, textX, textY, p);
    }

    /**
     * Draw the grid lines for the calendar
     * @param canvas The canvas to draw on.
     * @param p The paint used for drawing.
     */
    private static void drawGrid(Canvas canvas, int mCellWidth, int mCellHeight, Paint p) {
        p.setColor(mMonthBorderColor);
        p.setAntiAlias(false);

        final int width = canvas.getWidth();
        final int height = canvas.getHeight();

        for (int row = 0; row < CALENDAR_PAGE_WEEKS; row++) {
            int y = WEEK_GAP + row * (WEEK_GAP + mCellHeight) - 1;
            canvas.drawLine(0, y, width, y, p);
        }
        for (int column = 1; column < 7; column++) {
            int x = column * (MONTH_DAY_GAP + mCellWidth) - 1;
            canvas.drawLine(x, WEEK_GAP, x, height, p);
        }
    }

    private static void drawEvents(int topLeftJulianDay, int mCellWidth, int mCellHeight, Activity activity, Canvas canvas, Paint p, Rect r, int[] eventTextY) {
        // Get events within this area
        List<Instance> mInstances = loadEvents(topLeftJulianDay, activity);
    	
    	if (mInstances != null) {
	    	for (Instance instance: mInstances) {
	    		int startDay = instance.startDay;
	    		int endDay, startWeek, endWeek;
	    		
	    		// The event may start before the area
	    		if (startDay < topLeftJulianDay) {
	    			startDay = topLeftJulianDay;
	    		}
	    		startWeek = (int)Math.floor((startDay - topLeftJulianDay)/7.0);
	    		endWeek = (int)Math.floor((instance.endDay - topLeftJulianDay)/7.0);
	    		
	    		// The event may span to next week, loop to draw each week in that case
	    		if (startWeek < CALENDAR_PAGE_WEEKS) {
		    		do {
		    			if (startWeek < endWeek) {
		    				endDay = topLeftJulianDay + startWeek * 7 + 6; 
		        			drawEvent(topLeftJulianDay, startWeek, startDay, endDay, mCellWidth, mCellHeight, instance, canvas, p, r, eventTextY);
		        			startDay = topLeftJulianDay + startWeek * 7;
		    			} else {
		    				endDay = instance.endDay;
		        			drawEvent(topLeftJulianDay, startWeek, startDay, endDay, mCellWidth, mCellHeight, instance, canvas, p, r, eventTextY);
		    			}
		    			
		    			++startWeek;
		    		} while (startWeek < CALENDAR_PAGE_WEEKS && startWeek <= endWeek);
	    		}
	    	}
    	}
    }
    
    /**
     * Draw an event within a week (startDay and endDay should be within the same row when calling this function)
     * 
     * @param week the week of event
     * @param startDay the start julian day of the event
     * @param endDay the end julian day of the event
     * @param instance the event object
     * @param canvas the canvas to draw on
     * @param p the paint to use
     * @param r the rect object for reuse
     */
    private static void drawEvent(int mTopLeftJulianDay, int week, int startDay, int endDay, int mCellWidth, int mCellHeight, Instance instance, Canvas canvas, Paint p, Rect r, int[] eventTextY) {
    	int x = ((startDay - mTopLeftJulianDay) % 7) * (MONTH_DAY_GAP + mCellWidth);
    	int y = 0;
    	for (int i=startDay; i<=endDay; ++i) {
    		if (y < eventTextY[i-mTopLeftJulianDay]) {
    			y = eventTextY[i-mTopLeftJulianDay];
    		}
    	}

        p.setStyle(Paint.Style.FILL);
        p.setAntiAlias(true);
        p.setTypeface(null);
        p.setTextSize(EVENT_TEXT_SIZE);
        p.setColor(instance.color);
        p.setTextAlign(Paint.Align.LEFT);

        Paint.FontMetricsInt fm = p.getFontMetricsInt();
        r.left = x;
        r.top = y + EVENT_TEXT_TOP_MARGIN;
        r.right = ((endDay - mTopLeftJulianDay) % 7) * (MONTH_DAY_GAP + mCellWidth) + mCellWidth;
        int textY = y + EVENT_TEXT_TOP_MARGIN + Math.abs(fm.top);
        r.bottom = textY + Math.abs(fm.bottom);

        if (r.bottom <= (week+1) * (WEEK_GAP + mCellHeight)) {
	    	// Draw background if span more than a day
	        if (startDay < endDay) {
	        	p.setAlpha(50);
	        	canvas.drawRect(r, p);
	        	p.setAlpha(255);
	        }
	    	
	    	// Draw event text
	        r.right -= EVENT_TEXT_RIGHT_MARGIN;
	        canvas.save();
	        canvas.clipRect(r);
	        canvas.drawText(instance.title, x + EVENT_TEXT_LEFT_MARGIN, textY, p);
	        canvas.restore();
	        
	    	for (int i=startDay; i<=endDay; ++i) {
	   			eventTextY[i-mTopLeftJulianDay] = r.bottom;
	    	}
        }
    }
    
    // Re-create shadow bitmap and canvas for the new width and height
    private void drawingCalc(int width, int height) {
		mCellHeight = (height - (CALENDAR_PAGE_WEEKS * WEEK_GAP)) / CALENDAR_PAGE_WEEKS;
		mCellWidth = (width - (6 * MONTH_DAY_GAP)) / 7;
		//mLeftMargin = (width - mCellWidth * 7) / 2;  // calculate the remaining pixels due to division remains
		
        if (((mBitmap1 == null)
			|| mBitmap1.isRecycled()
			|| (mBitmap1.getHeight() != height)
			|| (mBitmap1.getWidth() != width))
                && (width > 0) && (height > 0)) {
			if (mBitmap1 != null) {
				mBitmap1.recycle();
			}
			mBitmap1 = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
			mCanvas1 = new Canvas(mBitmap1);
        }
        
        if (((mBitmap2 == null)
    			|| mBitmap2.isRecycled()
    			|| (mBitmap2.getHeight() != height)
    			|| (mBitmap2.getWidth() != width))
                    && (width > 0) && (height > 0)) {
    			if (mBitmap2 != null) {
    				mBitmap2.recycle();
    			}
    			mBitmap2 = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    			mCanvas2 = new Canvas(mBitmap2);
            }

        mBitmapRect.top = 0;
        mBitmapRect.bottom = height;
        mBitmapRect.left = 0;
        mBitmapRect.right = width;
        
        mCanvasRect.left = 0;
        mCanvasRect.right = width;
    }

    /**
     * Get events within a page of calendar
     * 
     * @param mTopLeftJulianDay top left julian day of the page
     * @param activity for calling calendar content provider
     * @return
     */
    private static List<Instance> loadEvents(int mTopLeftJulianDay, Activity activity) {
        Time tmpTime = new Time();
        tmpTime.setJulianDay(mTopLeftJulianDay);
        long begin = tmpTime.normalize(true) - 1000;
        tmpTime.setJulianDay(mTopLeftJulianDay + CALENDAR_PAGE_WEEKS*7);
        long end = tmpTime.normalize(true) + 1000;
        CPSyncUtil util = CPSyncUtil.getInstance();
        List<Instance> mInstances = util.getInstances(activity, util.getCalendars(activity, true), begin, end);
        /*
        StringBuffer eventsStr = new StringBuffer();
        if (mInstances != null) {
            for (Instance instance: mInstances) {
            	eventsStr.append(instance.getEventId() + ":" + instance.getCalendarId() + ":" + instance.getTitle() + ":" + SimpleDateFormat.getDateTimeInstance().format(new Date(Long.valueOf(instance.getBegin()))) + ":" + SimpleDateFormat.getDateTimeInstance().format(Long.valueOf(instance.getEnd())));
            	eventsStr.append("\n");
            }
            logger.info("Events=" + eventsStr);
        }
        */
        
        return mInstances;
    }
}
